package ro.theneckmaster.usbSync.gui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;

import ro.theneckmaster.usbSync.Folder;
import ro.theneckmaster.usbSync.FolderSyncAnalize;
import ro.theneckmaster.usbSync.FolderSyncExecute;
import ro.theneckmaster.usbSync.SyncronizeActionModel;

public class MainFrame extends JFrame implements ActionListener, PropertyChangeListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8026416994513756565L;
	
	JTextField textFieldLocalFolder;
	TextFieldInfo textFieldLocalNrFiles;
	TextFieldInfo textFieldLocalNrFolders;
	TextFieldInfo textFieldLocalSize;
	
	JTextField textFieldRemoteFolder;
	TextFieldInfo textFieldRemoteNrFiles;
	TextFieldInfo textFieldRemoteNrFolders;
	TextFieldInfo textFieldRemoteSize;
	
	FixedButton buttonLocalBrowse;
	FixedButton buttonRemoteBrowse;
	
	FixedButton buttonSyncronize;
	
	JRadioButton radioButtonRemote;
	JRadioButton radioButtonLocal;
	JRadioButton radioButtonNoRemove;
	
	JProgressBar progressBar;
	JLabel labelProgress = new JLabel("0/0");
	
	Folder folderLocal;
	Folder folderRemote;
	
	Folder incomingChanges;
	Folder outgoingChanges;
	
	FolderSyncAnalize folderSyncAnalize;
	FolderSyncExecute folderSyncExecute;
	
	JTabbedPane tabbedPane;
	JPanel fileInfoPanel;
	JPanel detailedInfoPanel;
	
	JTable actionInfoTable;
	
	private List<SyncronizeActionModel> actionQueue;

	public MainFrame() throws HeadlessException {
		super("usbSync");
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//setSize(300, 200);
		
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new BorderLayout(10, 10));
		
		tabbedPane = new JTabbedPane();
		fileInfoPanel = new JPanel();
		fileInfoPanel.setLayout(new BorderLayout(10, 10));
		detailedInfoPanel = new JPanel();
		detailedInfoPanel.setLayout(new BorderLayout(10, 10));
		
		// LOCAL PANEL
		
		JPanel panelLocal = new JPanel();
		panelLocal.setLayout(new BorderLayout(10, 10));
		JPanel panelSelectFolderLocal = new JPanel();
		panelSelectFolderLocal.setLayout(new BoxLayout(panelSelectFolderLocal, BoxLayout.X_AXIS));
		
		panelSelectFolderLocal.add(new JLabel("Local Folder: "));
		textFieldLocalFolder = new JTextField(30);
		panelSelectFolderLocal.add(textFieldLocalFolder);
		buttonLocalBrowse = new FixedButton("Browse");
		buttonLocalBrowse.addActionListener(this);
		panelSelectFolderLocal.add(buttonLocalBrowse);
		
		JPanel panelInfoLocal = new JPanel();
		panelInfoLocal.setLayout(new GridLayout(0, 4));
		panelInfoLocal.setBorder(BorderFactory.createTitledBorder("Local Folder Info"));
		
		panelInfoLocal.add(new JLabel("Files: "));
		textFieldLocalNrFiles = new TextFieldInfo();
		panelInfoLocal.add(textFieldLocalNrFiles);
		
		panelInfoLocal.add(new JLabel("Folders: "));
		textFieldLocalNrFolders = new TextFieldInfo();
		panelInfoLocal.add(textFieldLocalNrFolders);
		
		panelInfoLocal.add(new JLabel("Total Size: "));
		textFieldLocalSize = new TextFieldInfo();
		panelInfoLocal.add(textFieldLocalSize);
		
		panelLocal.add(panelSelectFolderLocal, BorderLayout.NORTH);
		panelLocal.add(panelInfoLocal, BorderLayout.CENTER);
		
//		mainPanel.add(panelLocal, BorderLayout.NORTH);
		fileInfoPanel.add(panelLocal, BorderLayout.NORTH);
		
		// REMOTE PANEL
		
		JPanel panelRemote = new JPanel();
		panelRemote.setLayout(new BorderLayout(10, 10));
		JPanel panelSelectFolderRemote = new JPanel();
		panelSelectFolderRemote.setLayout(new BoxLayout(panelSelectFolderRemote, BoxLayout.X_AXIS));
		
		panelSelectFolderRemote.add(new JLabel("Remote Folder: "));
		textFieldRemoteFolder = new JTextField(30);
		panelSelectFolderRemote.add(textFieldRemoteFolder);
		buttonRemoteBrowse = new FixedButton("Browse");
		buttonRemoteBrowse.addActionListener(this);
		panelSelectFolderRemote.add(buttonRemoteBrowse);
		
		JPanel panelInfoRemote = new JPanel();
		panelInfoRemote.setLayout(new GridLayout(0, 4));
		panelInfoRemote.setBorder(BorderFactory.createTitledBorder("Remote Folder Info"));
		
		panelInfoRemote.add(new JLabel("Files: "));
		textFieldRemoteNrFiles = new TextFieldInfo();
		panelInfoRemote.add(textFieldRemoteNrFiles);
		
		panelInfoRemote.add(new JLabel("Folders: "));
		textFieldRemoteNrFolders = new TextFieldInfo();
		panelInfoRemote.add(textFieldRemoteNrFolders);
		
		panelInfoRemote.add(new JLabel("Total Size: "));
		textFieldRemoteSize = new TextFieldInfo();
		panelInfoRemote.add(textFieldRemoteSize);
		
		panelRemote.add(panelSelectFolderRemote, BorderLayout.NORTH);
		panelRemote.add(panelInfoRemote, BorderLayout.CENTER);
		
//		mainPanel.add(panelRemote, BorderLayout.CENTER);
		fileInfoPanel.add(panelRemote, BorderLayout.CENTER);
		
		// OTHER USER INFORMATION
		
		radioButtonLocal = new JRadioButton("Local Folder");
		radioButtonRemote = new JRadioButton("Remote Folder");
		radioButtonNoRemove = new JRadioButton("Don't remove");
		
		ButtonGroup buttonGroup = new ButtonGroup();
		buttonGroup.add(radioButtonLocal);
		buttonGroup.add(radioButtonRemote);
		buttonGroup.add(radioButtonNoRemove);
		radioButtonLocal.addActionListener(this);
		radioButtonRemote.addActionListener(this);
		radioButtonNoRemove.addActionListener(this);
		
		JPanel panelOtherInfo = new JPanel(new BorderLayout(10,10));
		JPanel panelRemoving = new JPanel(new BorderLayout(10,10));
		panelRemoving.add(new JLabel("Delete files that don't exist in:"), BorderLayout.NORTH);
		
		JPanel panelRadios = new JPanel();
		panelRadios.setLayout(new BoxLayout(panelRadios, BoxLayout.X_AXIS));
		panelRadios.add(radioButtonLocal);
		panelRadios.add(radioButtonRemote);
		panelRadios.add(radioButtonNoRemove);
		radioButtonNoRemove.setSelected(true);
		
		panelRemoving.add(panelRadios, BorderLayout.CENTER);
		panelOtherInfo.add(panelRemoving, BorderLayout.NORTH);
		
		JPanel panelProgress = new JPanel(new BorderLayout(10, 10));
		JPanel panelProgressLabels = new JPanel();
		panelProgressLabels.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
		panelProgressLabels.add(labelProgress);
//		panelProgressLabels.add(new JLabel("Files Syncronized"));
		
		panelProgress.add(panelProgressLabels, BorderLayout.NORTH);
//		logArea = new JTextPane();
//		logArea.setEditable(false);
//		logArea.setPreferredSize(new Dimension(500, 300));
//		JScrollPane scrollPane = new JScrollPane();
//		scrollPane.setPreferredSize(new Dimension(500, 300));
//		scrollPane.add(logArea);
//		panelProgress.add(scrollPane, BorderLayout.NORTH);
		
		JPanel panelProgressButtons = new JPanel();
		panelProgressButtons.setLayout(new BoxLayout(panelProgressButtons, BoxLayout.X_AXIS));
		panelProgressButtons.add(new JLabel("Progress: "));
		progressBar = new JProgressBar();
		panelProgressButtons.add(progressBar);
		buttonSyncronize = new FixedButton("Syncronize");
		buttonSyncronize.addActionListener(this);
		panelProgressButtons.add(buttonSyncronize);
		
		panelProgress.add(panelProgressButtons, BorderLayout.CENTER);
		
		panelOtherInfo.add(panelProgress, BorderLayout.CENTER);
		
		tabbedPane.addTab("File Info", fileInfoPanel);
		tabbedPane.addTab("Action Details", detailedInfoPanel);
		
		mainPanel.add(tabbedPane, BorderLayout.CENTER);
		
		mainPanel.add(panelOtherInfo, BorderLayout.SOUTH);
		
		mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
		
		getContentPane().add(mainPanel);
		
		pack();
		
		setResizable(false);
		
	}


	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == buttonLocalBrowse) {
			JFileChooser fc = new JFileChooser(textFieldLocalFolder.getText());
			fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			int returnVal = fc.showOpenDialog(this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {

				File fileLocal = fc.getSelectedFile();
	            File fileRemote = new File("");
	            
	            String localFolderAbsolute = fileLocal.getAbsolutePath();
	            String[] localFolderArr = localFolderAbsolute.split("\\\\");
	            //This is where a real application would open the file.
	            //log.append("Opening: " + file.getName() + "." + newline);
	            textFieldLocalFolder.setText(fileLocal.getAbsolutePath());
	            textFieldRemoteFolder.setText(fileRemote.getAbsolutePath()+"\\"+localFolderArr[localFolderArr.length-1]);
	            progressBar.setIndeterminate(true);
				folderSyncAnalize = new FolderSyncAnalize();
				folderSyncAnalize.setMainFrame(this);
				folderSyncAnalize.addPropertyChangeListener(this);
				folderSyncAnalize.execute();
	        } else {
	            //log.append("Open command cancelled by user." + newline);
	        }
		} else if (e.getSource() == buttonRemoteBrowse) {
			JFileChooser fc = new JFileChooser(textFieldRemoteFolder.getText());
			fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			int returnVal = fc.showOpenDialog(this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {

				File fileRemote = fc.getSelectedFile();

	            textFieldRemoteFolder.setText(fileRemote.getAbsolutePath());
	            
	            progressBar.setIndeterminate(true);
				folderSyncAnalize = new FolderSyncAnalize();
				folderSyncAnalize.setMainFrame(this);
				folderSyncAnalize.addPropertyChangeListener(this);
				folderSyncAnalize.execute();

	        } else {
	            //log.append("Open command cancelled by user." + newline);
	        }
		} else if (e.getSource() == buttonSyncronize) {
			//folderLocal = new Folder(textFieldLocalFolder.getText());
			//folderRemote = new Folder(textFieldRemoteFolder.getText());
			progressBar.setIndeterminate(true);
			folderSyncExecute = new FolderSyncExecute();
			folderSyncExecute.setActionQueue(actionQueue);
			folderSyncExecute.addPropertyChangeListener(this);
			folderSyncExecute.execute();
            
		} else if (	(e.getSource() == radioButtonLocal) ||
					(e.getSource() == radioButtonRemote) ||
					(e.getSource() == radioButtonNoRemove) )
				{
			progressBar.setIndeterminate(true);
			folderSyncAnalize = new FolderSyncAnalize();
			folderSyncAnalize.setMainFrame(this);
			folderSyncAnalize.addPropertyChangeListener(this);
			folderSyncAnalize.execute();
		}
		
	}
	
	public void doneLoadingFolders() {
		textFieldLocalNrFiles.setText(""+folderLocal.getFilesNr());
        textFieldLocalNrFolders.setText(""+folderLocal.getSubFolderNr());
        textFieldLocalSize.setText(getFileSizeString(folderLocal.getTotalSize()));
        
        textFieldRemoteNrFiles.setText(""+folderRemote.getFilesNr());
        textFieldRemoteNrFolders.setText(""+folderRemote.getSubFolderNr());
        textFieldRemoteSize.setText(getFileSizeString(folderRemote.getTotalSize()));
        progressBar.setIndeterminate(false);
	}
	
	public String getFileSizeString(long size) {
		
		double kbSize=0, mbSize =0, gbSize =0;
		
		if (size > 1024) {
			kbSize = ((double)size)/1024;
		}
		if (kbSize > 1024) {
			mbSize = kbSize/1024;
		}
		if (mbSize > 1024) {
			gbSize = mbSize/1024;
		}
		
		DecimalFormat df = new DecimalFormat("#,##0.##");
		
		if (gbSize>0) {
			return df.format(gbSize)+" GB"; 
		}
		if (mbSize>0) {
			return df.format(mbSize)+" MB"; 
		}
		if (kbSize>0) {
			return df.format(kbSize)+ "KB"; 
		}
				
		return size+" bytes";
		
	}


	@SuppressWarnings("unchecked")
	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		// TODO Auto-generated method stub
		if (evt.getPropertyName().equals("progress")) {
			int progress = (Integer) evt.getNewValue();
			progressBar.setValue(progress);
		} else if (evt.getPropertyName().equals("message")) {
//			System.out.println("propertyChangeListener: "+evt.getPropertyName());
            String message = (String)evt.getNewValue();
            //progressBar.setIndeterminate(false);
            //progressBar.setValue(progress);
//            System.out.println("MESSAGE: "+message);
            labelProgress.setText(message);
        } else if (evt.getPropertyName().equals("startProgress")) {
        	int maxProgress = (Integer) evt.getNewValue();
        	progressBar.setIndeterminate(false);
        	progressBar.setStringPainted(true);
        	progressBar.setMaximum(maxProgress);
        } else if (evt.getPropertyName().equals("actionQueue")) {
        	actionQueue = (List<SyncronizeActionModel>) evt.getNewValue();
        	createTable();
        }
	}
	
	private void createTable() {
		
		String[] columnNames = {"id", "Action",
                "Source", "Destination"
                };
		
		Object[][] data = new Object[actionQueue.size()][4];
		for (Iterator<SyncronizeActionModel> iterator = actionQueue.iterator(); iterator.hasNext();) {
			SyncronizeActionModel actionModel = (SyncronizeActionModel) iterator.next();
			data[actionModel.getId()][0] = actionModel.getId();
			data[actionModel.getId()][1] = actionModel.getActionName();
			data[actionModel.getId()][2] = actionModel.getSourcePath();
			data[actionModel.getId()][3] = actionModel.getDestPath();
		}
		System.out.println("QUEUE: "+actionQueue.size());
		if (actionInfoTable != null) {
			// TODO de facut sa faca update la tabela de action
			detailedInfoPanel.removeAll();
		}
		
		actionInfoTable = new JTable(data, columnNames);
		JScrollPane scrollPane = new JScrollPane(actionInfoTable);
		detailedInfoPanel.add(actionInfoTable.getTableHeader(), BorderLayout.PAGE_START);
		detailedInfoPanel.add(scrollPane, BorderLayout.CENTER);
		this.repaint();
	}

	public JTextField getTextFieldLocalFolder() {
		return textFieldLocalFolder;
	}


	public void setTextFieldLocalFolder(JTextField textFieldLocalFolder) {
		this.textFieldLocalFolder = textFieldLocalFolder;
	}


	public TextFieldInfo getTextFieldLocalNrFiles() {
		return textFieldLocalNrFiles;
	}


	public void setTextFieldLocalNrFiles(TextFieldInfo textFieldLocalNrFiles) {
		this.textFieldLocalNrFiles = textFieldLocalNrFiles;
	}


	public TextFieldInfo getTextFieldLocalNrFolders() {
		return textFieldLocalNrFolders;
	}


	public void setTextFieldLocalNrFolders(TextFieldInfo textFieldLocalNrFolders) {
		this.textFieldLocalNrFolders = textFieldLocalNrFolders;
	}


	public TextFieldInfo getTextFieldLocalSize() {
		return textFieldLocalSize;
	}


	public void setTextFieldLocalSize(TextFieldInfo textFieldLocalSize) {
		this.textFieldLocalSize = textFieldLocalSize;
	}


	public JTextField getTextFieldRemoteFolder() {
		return textFieldRemoteFolder;
	}


	public void setTextFieldRemoteFolder(JTextField textFieldRemoteFolder) {
		this.textFieldRemoteFolder = textFieldRemoteFolder;
	}


	public TextFieldInfo getTextFieldRemoteNrFiles() {
		return textFieldRemoteNrFiles;
	}


	public void setTextFieldRemoteNrFiles(TextFieldInfo textFieldRemoteNrFiles) {
		this.textFieldRemoteNrFiles = textFieldRemoteNrFiles;
	}


	public TextFieldInfo getTextFieldRemoteNrFolders() {
		return textFieldRemoteNrFolders;
	}


	public void setTextFieldRemoteNrFolders(TextFieldInfo textFieldRemoteNrFolders) {
		this.textFieldRemoteNrFolders = textFieldRemoteNrFolders;
	}


	public TextFieldInfo getTextFieldRemoteSize() {
		return textFieldRemoteSize;
	}


	public void setTextFieldRemoteSize(TextFieldInfo textFieldRemoteSize) {
		this.textFieldRemoteSize = textFieldRemoteSize;
	}


	public FixedButton getButtonLocalBrowse() {
		return buttonLocalBrowse;
	}


	public void setButtonLocalBrowse(FixedButton buttonLocalBrowse) {
		this.buttonLocalBrowse = buttonLocalBrowse;
	}


	public FixedButton getButtonRemoteBrowse() {
		return buttonRemoteBrowse;
	}


	public void setButtonRemoteBrowse(FixedButton buttonRemoteBrowse) {
		this.buttonRemoteBrowse = buttonRemoteBrowse;
	}


	public FixedButton getButtonSyncronize() {
		return buttonSyncronize;
	}


	public void setButtonSyncronize(FixedButton buttonSyncronize) {
		this.buttonSyncronize = buttonSyncronize;
	}


	public JRadioButton getRadioButtonRemote() {
		return radioButtonRemote;
	}


	public void setRadioButtonRemote(JRadioButton radioButtonRemote) {
		this.radioButtonRemote = radioButtonRemote;
	}


	public JRadioButton getRadioButtonLocal() {
		return radioButtonLocal;
	}


	public void setRadioButtonLocal(JRadioButton radioButtonLocal) {
		this.radioButtonLocal = radioButtonLocal;
	}


	public JRadioButton getRadioButtonNoRemove() {
		return radioButtonNoRemove;
	}


	public void setRadioButtonNoRemove(JRadioButton radioButtonNoRemove) {
		this.radioButtonNoRemove = radioButtonNoRemove;
	}


	public JProgressBar getProgressBar() {
		return progressBar;
	}


	public void setProgressBar(JProgressBar progressBar) {
		this.progressBar = progressBar;
	}


	public JLabel getLabelProgress() {
		return labelProgress;
	}


	public void setLabelProgress(JLabel labelProgress) {
		this.labelProgress = labelProgress;
	}


	public Folder getFolderLocal() {
		return folderLocal;
	}


	public void setFolderLocal(Folder folderLocal) {
		this.folderLocal = folderLocal;
	}


	public Folder getFolderRemote() {
		return folderRemote;
	}


	public void setFolderRemote(Folder folderRemote) {
		this.folderRemote = folderRemote;
	}


	public Folder getIncomingChanges() {
		return incomingChanges;
	}


	public void setIncomingChanges(Folder incomingChanges) {
		this.incomingChanges = incomingChanges;
	}


	public Folder getOutgoingChanges() {
		return outgoingChanges;
	}


	public void setOutgoingChanges(Folder outgoingChanges) {
		this.outgoingChanges = outgoingChanges;
	}


	public List<SyncronizeActionModel> getActionQueue() {
		return actionQueue;
	}


	public void setActionQueue(List<SyncronizeActionModel> actionQueue) {
		this.actionQueue = actionQueue;
	}

}
